/* CsJni - .NET / Java Bridge
 * 
 * Copyright 2010 Robert E. Burke Licensed under the Apache License, Version 
 * 2.0 (the "License"); you may not use this file except in compliance with 
 * the License. You may obtain a copy of the License at 
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable 
 * law or agreed to in writing, software distributed under the License is 
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
 * KIND, either express or implied. See the License for the specific language 
 * governing permissions and limitations under the License. 
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics.CodeAnalysis;

namespace CsJni
{
    public class JniMethod : JniMember
    {
        internal JniMethod(IntPtr handle, JniClass declaringClass, bool isStatic, string signature)
            : base(handle, declaringClass, isStatic, signature)
        {
        }

        public JniObject CallObjectMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyObjectReturnType();
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            IntPtr result = JniEnvironment.Functions.CallObjectMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return JniObject.CreateReturnObject(environment, result, this);
        }

        public string CallStringMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.String);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            IntPtr result = JniEnvironment.Functions.CallObjectMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return JniString.ExtractAndRelease(environment, result);
        }

        public bool CallBooleanMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Boolean);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            byte result = JniEnvironment.Functions.CallBooleanMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return JBooleanConverter.From(result);
        }

        public byte CallByteMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Byte);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            byte result = JniEnvironment.Functions.CallByteMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        public char CallCharMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Char);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            char result = JniEnvironment.Functions.CallCharMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "short")]
        public short CallShortMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Short);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            short result = JniEnvironment.Functions.CallShortMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")]
        public int CallIntMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Int);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            int result = JniEnvironment.Functions.CallIntMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "long")]
        public long CallLongMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Long);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            long result = JniEnvironment.Functions.CallLongMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "float")]
        public float CallFloatMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Float);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            float result = JniEnvironment.Functions.CallFloatMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        public double CallDoubleMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Double);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            double result = JniEnvironment.Functions.CallDoubleMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        public void CallVoidMethod(
            JniEnvironment environment,
            JniObject jniObject,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Void);
            VerifyEnvironment(environment);
            VerifyNotStatic();
            VerifyInputJniObject(jniObject);
            // NOTE: OK if "JValue[] arguments" is null
            JniEnvironment.Functions.CallVoidMethodA(environment.Handle, jniObject.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
        }

        public JniObject CallStaticObjectMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyObjectReturnType();
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            IntPtr result = JniEnvironment.Functions.CallStaticObjectMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return JniObject.CreateReturnObject(environment, result, this);
        }

        public string CallStaticStringMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.String);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            IntPtr result = JniEnvironment.Functions.CallStaticObjectMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return JniString.ExtractAndRelease(environment, result);
        }


        public bool CallStaticBooleanMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Boolean);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            byte result = JniEnvironment.Functions.CallStaticBooleanMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return JBooleanConverter.From(result);
        }

        public byte CallStaticByteMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Byte);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            byte result = JniEnvironment.Functions.CallStaticByteMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        public char CallStaticCharMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Char);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            char result = JniEnvironment.Functions.CallStaticCharMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "short")]
        public short CallStaticShortMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Short);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            short result = JniEnvironment.Functions.CallStaticShortMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "int")]
        public int CallStaticIntMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Int);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            int result = JniEnvironment.Functions.CallStaticIntMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "long")]
        public long CallStaticLongMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Long);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            long result = JniEnvironment.Functions.CallStaticLongMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        // OK to suppress, match JNI name & signature
        [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "float")]
        public float CallStaticFloatMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Float);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            float result = JniEnvironment.Functions.CallStaticFloatMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        public double CallStaticDoubleMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Double);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            double result = JniEnvironment.Functions.CallStaticDoubleMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
            return result;
        }

        public void CallStaticVoidMethod(
            JniEnvironment environment,
            JValue[] arguments
            )
        {
            VerifyReturnType(JniType.Void);
            VerifyEnvironment(environment);
            VerifyStatic();
            // NOTE: OK if "JValue[] arguments" is null
            JniEnvironment.Functions.CallStaticVoidMethodA(environment.Handle, this.DeclaringClass.Handle, this.Handle, arguments);
            JniThrowable.CheckException(environment);
        }
    }
}
